package dal;

import gui.GameConstants;
import gui.event.HexGrid;

import java.awt.Dimension;
import java.awt.Point;
import java.io.Serializable;
import java.util.Vector;

import dal.object.*;
import dal.object.grounds.Abyss;
import dal.object.grounds.Grass;
import dal.object.rocks.MarbleRock;

public class MapStruct implements Serializable {
	private static final long serialVersionUID = 2L;
	private int startX, startY;    //the map's upper-left corner
	private int ballX, ballY;
	private int cards;
	private Dimension dimension;
	private Dimension size;	// drawing panel's size
	private String description;
	private String name;
	private Vector<MapObject> grounds;
	private Vector<MapObject> rocks;
	private Vector<MapObject> attackers;
	private Vector<MapObject> tools;
	
	public MapStruct(MapFileStruct mfs) {
		setStructure(mfs);
	}
	
	public MapStruct(int w, int h) {
		this.setDimension(w, h);
		grounds = new Vector<MapObject>();
		rocks = new Vector<MapObject>();
		tools = new Vector<MapObject>();
		attackers = new Vector<MapObject>();
		test();
	}
	
	public MapStruct() {
		this.setDimension(40, 50);
		grounds = new Vector<MapObject>();
		rocks = new Vector<MapObject>();
		tools = new Vector<MapObject>();
		attackers = new Vector<MapObject>();
		test();
	}
	
	private void test(){
		int nn = dimension.width * dimension.height;
		
		for(int i = 0; i < nn; ++i){
/*			int r = (int) (Math.random() * 10);
			
			switch(r) {
			case 0 :
				grounds.add(new Sand());
				break;
			case 1 :
				grounds.add(new Ice());
				break;
			default :
				grounds.add(new Grass());
				break;
			}*/
			grounds.add(new Grass());
		}
		
		for(int i = 0; i < nn; ++i){
			if((int) (Math.random() * 100) == 0) {
				rocks.add(new MarbleRock());
			} else {
				rocks.add(null);
			}
		}
		
		for(int i = 0; i < nn; ++i){
			tools.add(null);
		}
	}
	
	/**
	 * @param ms
	 * 	a MapFileStruct
	 * converts the structure into a MapStruct structure
	 */
	public void setStructure(MapFileStruct mfs){
		this.dimension = mfs.getDimension();
		this.size = mfs.getSize();
		this.description = mfs.getDescription();
		this.name = mfs.getName();
		Point ball = mfs.getBallPosition();
		this.ballX = ball.x;
		this.ballY = ball.y;
		Point corner = mfs.getUpperLeftCorner();
		this.startX = corner.x;
		this.startY = corner.y;
		this.cards = mfs.getNumberOfCards();
		
		grounds = new Vector<MapObject>();
		rocks = new Vector<MapObject>();
		tools = new Vector<MapObject>();
		attackers = new Vector<MapObject>();
		
		for(Integer i : mfs.getGroundsVector()){
			if(i < 0){
				grounds.add(new Abyss());
			} else {
				grounds.add(HexGrid.newInstace(GameConstants.GROUND_LIST[i]));
			}
		}
		for(Integer i : mfs.getRockVector()){
			if(i < 0) {
				rocks.add(null);
			} else {
				rocks.add(HexGrid.newInstace(GameConstants.ROCK_LIST[i]));
			}
		}
		for(Integer i : mfs.getAttackerVector()){
			if(i < 0) {
				attackers.add(null);
			} else { 
				attackers.add(HexGrid.newInstace(GameConstants.ATTACKER_LIST[i]));
			}
		}
		for(Integer i : mfs.getToolVector()){
			if(i < 0) {
				tools.add(null);
			} else {
				tools.add(HexGrid.newInstace(GameConstants.TOOL_LIST[i]));
			}
		}
	}
	
	//changing the coordinates of the upper-left corner
	public void setUpperLeftCorner(int startX, int startY){
		this.startX = startX;
		this.startY = startY;
	}
	
	//reading the coordinates of the upper-left corner
	public Point getUpperLeftCorner(){
		return new Point(startX, startY);
	}
	
	//reading the coordinates of the ball
	public void setBallPosition(int ballX, int ballY){
		this.ballX = ballX;
		this.ballY = ballY;
	}
	
	//changing the coordinates of the ball
	public Point getBallPosition(){
		return new Point(ballX, ballY);
	}
	
	//setting the dimension of the map
	public void setDimension(int x, int y){
		this.dimension = new Dimension(x, y);
		this.size = createMapSize(dimension);
	}
	
	//reading the the dimension of the map
	public Dimension getDimension(){
		return this.dimension;
	}
	
	// reading drawing panel's size 
	public Dimension getSize() {
		return this.size;
	}
	
	public void setDescription(String descript){
		this.description = descript;
	}
	
	public String getDescription(){
		return this.description;
	}
	
	public Vector<MapObject> getGroundsVector(){
		return grounds;
	}
	
	public Vector<MapObject> getRockVector(){
		return rocks;
	}
	
	public Vector<MapObject> getAttackerVector(){
		return attackers;
	}
	
	public Vector<MapObject> getToolVector(){
		return tools;
	}
	
	/**
	 * @param dim
	 * 	contains the number of hexagons in both horizontal and vertical directions
	 * @return 
	 * 	dimensions of the panel size
	 */
	public static Dimension createMapSize(Dimension dim){
		int w = dim.width * GameConstants.picWidth100 + ((dim.height > 1) ? GameConstants.picWidth50 : 0);
		int h = dim.height * GameConstants.picHeight75 + GameConstants.picHeight25;
		return new Dimension(w, h); 
	}

	/**
	 * @param mo
	 * 	a MapObject
	 * @return
	 * 	a vector containing the same type of mapObjects or
	 * null if the class don't have the vector
	 */
	public Vector<MapObject> getVectorByType(MapObject mo) {
    	if(mo instanceof Ground) {
    		return grounds;
    	} else if(mo instanceof Rock) {
    		return rocks;
    	} else if(mo instanceof Tool) {
    		return tools;
    	} else if(mo instanceof Attacker) {
    		return attackers;
    	} else {
    		return null;
    	}
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public String getName() {
		return this.name;
	}

	public void setNumberOfCards(int cards) {
		this.cards = cards;
	}
	
	public int getNumberOfCards() {
		return cards;
	}
}
